package ig.finanzas;

import ig.finanzas.riesgo.FactorRiesgoPersonal;

import ig.metrica.escenario.GeneraEscenarioBean;
import ig.util.excepciones.DatoInvalidoExcepcion;

import ig.util.excepciones.LogicaExcepcion;

//import java.io.FileNotFoundException;

import java.rmi.RemoteException;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.ArrayList;

import java.util.Collection;

import java.util.Date;

import javax.ejb.FinderException;

/**
 *
 * Implementa los metodos y funciones de un contrato que no puede ser atomizable o desmaterializable.
 *
 * Para este tipo de contrato no se manejan valores registrados.
 *
 * @author lfgarcia
 *
 */
public class ContratoSimpleBean extends ContratoBean {

    static final long serialVersionUID = 01;
    /**
     *
     * @uml.property  name="nombre"
     *
     */
    private String nombre;
    /**
     *
     * @uml.property  name="tipo"
     *
     */
    private String tipo;

    /**
     *
     * Devuelve el nombre del contrato.
     *
     * @return
     *
     * @uml.property  name="nombre"
     *
     */
    public String getNombre() {

        return nombre;

    }

    /**
     *
     * Devuelve el tipo de contrato. Los valores validos son Disponible para la Venta y  negociables.
     *
     * @return
     *
     * @uml.property  name="tipo"
     *
     */
    public String getTipo() {

        return tipo;

    }

    /**
     *
     * @param tipo  The tipo to set.
     *
     * @uml.property  name="tipo"
     *
     */
    public void setTipo(String tipo) throws DatoInvalidoExcepcion, Exception {

        if (!tipo.equals(ContratoSimple.TIPO_DISPONIBLEVENTA) && !tipo.equals(ContratoSimple.TIPO_NEGOCIABLE)) {

            throw new DatoInvalidoExcepcion("El tipo especificado para la posicion " + ((ContratoPK) ctx.getPrimaryKey()).toString() + " no es valido");

        }

        this.tipo = tipo;

    }

    /**
     *
     * Calcula el valor en riesgo del contrato.
     *
     * @param fecha
     *
     * @param numdias Este parametro solo se utiliza cuando como tasa de referencia se utiliza la curva cero cupon
     *
     * exclusivamente para el calculo de la volatilidad de la misma.
     *
     * @param factor
     *
     * @return
     *
     * @throws DatoInvalidoExcepcion Si la fecha o el factor especificado son nulos, o si el factor de riesgo definido
     *
     * no es de tipo tasa, o si el valor de la tasa en esa fecha es menor o igual a -1.
     *
     * @throws LogicaExcepcion Si el contrato no tiene flujos,
     *
     * o si no se puede determinar el valor de la tasa en dicha fecha.
     *
     * @throws FinderException Si no se puede cargar la tasa de descuento.
     *
     */
    public double valorEnRiesgo(Date fecha, int numdias, FactorRiesgoPersonal factor)
            throws DatoInvalidoExcepcion, LogicaExcepcion, FinderException {

        //VER = ValorDeMercado * duracion / (1+TIR) * cambioesperado



        if (fecha == null) {
            throw new DatoInvalidoExcepcion("La fecha especificada es nula.");
        }



        if (factor == null) {
            throw new DatoInvalidoExcepcion("El factor de riesgo especificado es nulo.");
        }



        if (factor.getTipo() != FactorRiesgoPersonal.TIPO_FACTORTASA) {
            throw new DatoInvalidoExcepcion("El factor de riesgo especificado debe ser del tipo tasa.");
        }



        ManejadorFlujos flujosduracion = flujosParaDuracion(fecha);



        Tasa tasa = getTasa(factor.getTasaPK());



        double valorDeMercado = flujosduracion.valorDescontado(tasa, fecha);

        double duracion = flujosduracion.duracion(fecha, tasa);

        double tir = flujosduracion.tir();



        double cambioesperado = 0;

        if (factor.getTipoCalculoCambioEsperado() == FactorRiesgoPersonal.CAMBIOESPERADO_FACTORMATRIZ) {
            cambioesperado = factor.getFactorRiesgoMatrizCorrelacion().getCambioEsperado();
        } else {

            try {

                cambioesperado = tasa.cambioEsperadoValoresRegistrados(fecha, factor.getDefinidorCalculoCambioEsperado());

            } catch (RemoteException e) {

            }

        }



        double ver = valorDeMercado * duracion / (1 + tir) * cambioesperado;



        return ver;

    }

    public void eliminarEntidad() {
    }

    public void actualizarEntidad() {
    }

    public void cargarEntidad() throws DatoInvalidoExcepcion, SQLException, Exception {
        Statement st = null;
        ResultSet r1 = null;
        try {
            ContratoPK contratoPK = (ContratoPK) ctx.getPrimaryKey();
            Long idInterna = contratoPK.getIdInterna();
            conn = getConexion("METRICADB");
            st = conn.createStatement();
            String txtsql = "SELECT C.NOMBRE AS CONTRATO, C.TIPO AS TIPO, M.NOMBRE AS MONEDA  " +
                    "FROM CONTRATOSSIMPLES C, PRODUCTOS P, MONEDAS M, CONTRATOS C2  " +
                    "WHERE C2.IDPRODUCTO=P.ID AND P.IDMONEDA=M.ID AND C.ID=C2.ID AND C.ID='" + idInterna + "'";

            r1 = st.executeQuery(txtsql);
            r1.next();
            //Carga de los atributos especificos
            this.nombre = r1.getString("CONTRATO");
            setTipo(r1.getString("TIPO"));
            //Carga de los atributos generales
            this.monedaPK = new MonedaPK(r1.getString("MONEDA"));
            cargarProductoPK(idInterna);
            cargarFlujos(idInterna);
            cargarTasasDePago(idInterna);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                conn.close();
            } catch (Exception e) {
            }
            try {
                st.close();
            } catch (Exception e) {
            }
            try {
                r1.close();
            } catch (Exception e) {
            }
        }
    }

    public ContratoPK ejbFindByPrimaryKey(ContratoPK pk) throws FinderException {
        ResultSet r1 = null;
        try {
            conn = getConexion("METRICADB");
            pstmt1 = conn.prepareStatement(
                    "SELECT ID " +
                    "FROM CONTRATOSSIMPLES " +
                    "WHERE ID=?");
            pstmt1.setLong(1, pk.getIdInterna());
            r1 = pstmt1.executeQuery();
            if (r1.next() == false) {
                throw new FinderException("No fue posible encontrar el contrato simple " + pk.toString());
            }

            return pk;
        } catch (Exception e) {
            throw new FinderException("No fue posible cargar el contrato simple " + pk.toString());
        } finally {
            try {
                pstmt1.close();
            } catch (SQLException e) {
            }
            try {
                conn.close();
            } catch (SQLException e) {
            }
            try {
                r1.close();
            } catch (SQLException e) {
            }
        }
    }

    public Collection ejbFindAll() throws FinderException {
        ArrayList contratos = new ArrayList();
        ResultSet rs = null;
        try {
            conn = getConexion("METRICADB");
            pstmt1 = conn.prepareStatement( "SELECT ID "+"FROM CONTRATOSSIMPLES ");
            rs = pstmt1.executeQuery();
            while (rs.next()) {
                contratos.add(new ContratoPK(rs.getLong("ID")));
            }
        } catch (Exception e) {
            throw new FinderException(e.toString());
        } finally {
            try {
                pstmt1.close();
            } catch (SQLException e) {
            }
            try {
                conn.close();
            } catch (SQLException e) {
            }
            try {
                rs.close();
            } catch (SQLException e) {
            }
        }
        return contratos;
    }
}
